#define _GNU_SOURCE
#include <error.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sysexits.h>
#include <libconfig.h>
#include "config.h"

xmw_config_t xmw_config_parse(const char* config_file)
{
	config_t xmw_config;
	config_setting_t *bots_config;
	FILE *xmw_conffile;
	const char *xmw_conffile_version;
	xmw_config_t config_data;

	/* Open configuration file */
	config_init(&xmw_config);
	xmw_conffile = fopen(config_file, "r");
	if (NULL == xmw_conffile)
	{
		error(EX_IOERR, errno, "Cannot open config file %s",
				config_file);
	}
	/* Read configuration file */
	if (CONFIG_TRUE != config_read(&xmw_config, xmw_conffile))
	{
		error(EX_CONFIG, 0,
				"Cannot parse config file %s: %s at line %d",
				config_file,
				config_error_text(&xmw_config),
				config_error_line(&xmw_config));

	}
	/* No more need of file descriptor */
	fclose(xmw_conffile);
	/* Check config file version */
	xmw_conffile_version = config_lookup_string(&xmw_config, "version");
	if ((NULL == xmw_conffile_version) ||
			(0 > strverscmp(XMW_CONFIG_VERSION,
					xmw_conffile_version)))
	{
		error(EX_CONFIG, 0,
				"Unsupported config version %s. Supported version is %s",
				xmw_conffile_version, XMW_CONFIG_VERSION);
	}
	/* Fill bots array */
	bots_config = config_lookup(&xmw_config, "robots");
	if (NULL == bots_config)
	{
		error(EX_CONFIG, 0,
				"Bots configuration not found in config file");
	}
	config_data.bots.size = config_setting_length(bots_config);
	if (0 == config_data.bots.size)
	{
		error(EX_CONFIG, 0, "Empty bots list on line %d",
				config_setting_source_line(bots_config));
	}
	config_data.bots.bots = (xmw_bot_t*)malloc(config_data.bots.size * sizeof(xmw_bot_t));
	for (int i = 0; i < config_data.bots.size; i++)
	{
		config_data.bots.bots[i].command = config_data.bots.bots[i].jid = NULL;
		config_setting_t *element = config_setting_get_elem(bots_config, i);
		config_setting_t *value = config_setting_get_member(element, "jid");
		const char *tempstring;
		if (NULL != value)
		{
			tempstring = config_setting_get_string(value);
			if (NULL != tempstring)
			{
				config_data.bots.bots[i].jid = (char*)malloc((strlen(tempstring) + 1) * sizeof(char));
				strcpy(config_data.bots.bots[i].jid, tempstring);
			}
		}
		if (NULL == config_data.bots.bots[i].jid)
		{
			error(EX_CONFIG, 0,
					"Cannot get JID for bot %d on line %d",
					i, config_setting_source_line(bots_config));
		}
		value = config_setting_get_member(element, "command");
		if (NULL != value)
		{
			tempstring = config_setting_get_string(value);
			if (NULL != tempstring)
			{
				config_data.bots.bots[i].command = (char*)malloc((strlen(tempstring) + 1) * sizeof(char));
				strcpy(config_data.bots.bots[i].command, tempstring);
			}
		}
		if (NULL == config_data.bots.bots[i].command)
		{
			error(EX_CONFIG, 0,
					"Cannot get command for bot %d on line %d",
					i, config_setting_source_line(element));
		}
	}
	config_destroy(&xmw_config);
	return config_data;
}

/* This function will not free the bots structure itself because there is
 * no need to make it dynamic. So only internal strings and bots.bots property
 * will be freed */
void xmw_config_free(xmw_config_t *config)
{
	for (int i = 0; i < config->bots.size; i++)
	{
		free(config->bots.bots[i].jid);
		free(config->bots.bots[i].command);
	}
	free (config->bots.bots);
	config->bots.size = 0;
	config->bots.bots = NULL;
}
